﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
/*
namespace Xww.LCV.Model {
    public class ThresholdVetexDict : VetexDict {

        public int Threshold { get; set; }
        public int MinSpan { get; set; }
        public int MaxSpan { get; set; }

        public ThresholdVetexDict(int threshold, int minSpan, int maxSpan) {
            this.Threshold = threshold;
            this.MinSpan = minSpan;
            this.MaxSpan = maxSpan;
            if (this.Threshold <= 1) {
                throw new ArgumentException("Threshold is too low. It should be greater than 1.");
            }
        }

        public override IList<LCS> ExtractMotifs(IEnumerable<SequencePath> listPaths) {
            List<LCS> rst = new List<LCS>();
            //int MinSpan = 
            int[] indexArray;
            // 获取第一步产生的单单元LCV
            ICollection<LCS> stepLCSs = new HashSet<LCS>(GetSingleUnitLCSs(listPaths, out indexArray), LCS.InstanceForHash);
            rst.AddRange(stepLCSs);
            //return rst;
            while (stepLCSs.Count > 1) {
                var groups = stepLCSs.GroupBy(o => o.SubFirstLCS, LCS.InstanceForHash).ToArray();                
                //HashSet<LCS> currentLCS = new HashSet<LCS>(LCS.InstanceForHash);
                ICollection<LCS> currentLCS = new List<LCS>();
                foreach (var group in groups) {
                    var sortedGroup = group.ToArray();
                        //group.OrderBy(o => o[o.Length - 1].Location).ToArray();
                    for (int i = 0; i < sortedGroup.Length-1; i++) {
                        LCS the = sortedGroup[i];
                        for (int j = i+1; j < sortedGroup.Length; j++) {
                            LCS other = sortedGroup[j];
                            if (the.LastLocation == other.LastLocation)
                                continue;
                            LCS big = LCS.Imerge(the, other);
                            var bigList = this[big[0].AA.ToString()].AsEnumerable();  //第一个顶点上对应的所有结点
                            for (int index = 1; index < big.Length; index++) {
                                int lastLocation = big[index - 1].Location;
                                int stepCount = big[index].Location - lastLocation;   // 根据和上一步骤位置的差值，计算出移动步长。
                                for (int step = 0; step < stepCount; step++) {
                                    bigList = bigList.MoveAllNext();
                                }
                                bigList = bigList.Where(o => o.Value[0] == big[index].AA);
                                big.Support = bigList.Count();
                                if (big.Support < Threshold)
                                    break;                                
                            }
                            if (big.Support >= Threshold)
                                currentLCS.Add(big);
                        }
                    }
                }
                //currentLCS = new HashSet<LCS>(currentLCS.OrderBy(o => o), LCS.InstanceForHash);
                rst.AddRange(currentLCS);
                stepLCSs = currentLCS;
            }
            return rst;

            #region Unused
            //
            while (stepLCSs.Count > 1) {
                //var stepLCSs= stepLCSs.OrderBy(o => o[1].Location).ToArray();
                var alreadyCheckedLCSList = new HashSet<LCS>(LCS.InstanceForHash);
                HashSet<LCS> currentLCS = new HashSet<LCS>(LCS.InstanceForHash);
                //遍历每一步骤的两两LCV组合
                for (int formerLCVIndex = 0; formerLCVIndex < stepLCSs.Count - 1; formerLCVIndex++) {
                    LCS the = stepLCSs.ElementAt(formerLCVIndex);
                    //先查找能与其组合的，再进行拼接
                    //var properLCSSet = stepLCSs.Where(o=>o[0].Equals(the[0])).Where(
                    //
                    //stepLCSs[formerLCVIndex];
                    for (int latterLCVIndex = formerLCVIndex + 1; latterLCVIndex < stepLCSs.Count; latterLCVIndex++) {
                        LCS other = stepLCSs.ElementAt(latterLCVIndex);
                        //stepLCSs[latterLCVIndex];
                        if (!LCS.CanImerge(the, other)) { continue; }
                        LCS big = LCS.Imerge(the, other);
                        if (alreadyCheckedLCSList.Contains(big)) { continue; }
                        var bigList = this[big[0].AA.ToString()].AsEnumerable();  //第一个顶点上对应的所有结点
                        for (int index = 1; index < big.Length; index++) {
                            int lastLocation = big[index - 1].Location;
                            int stepCount = big[index].Location - lastLocation;   // 根据和上一步骤位置的差值，计算出移动步长。
                            for (int step = 0; step < stepCount; step++) {
                                bigList = bigList.MoveAllNext();
                                //if ((big.Support = bigList.Count()) < Threshold) {
                                //    break;
                                //}
                            }
                            bigList = bigList.Where(o => o.Value == big[index].AA.ToString()).ToList();
                            big.Support = bigList.Count();
                            if (big.Support < Threshold) {
                                break;
                            }
                        }
                        alreadyCheckedLCSList.Add(big);
                        if (big.Support >= Threshold) {
                            currentLCS.Add(big);
                        }
                    }
                }
                currentLCS = new HashSet<LCS>(currentLCS.OrderBy(o => o), LCS.InstanceForHash);
                rst.AddRange(currentLCS);
                stepLCSs = currentLCS;
            }
            return rst;
            #endregion
        }

        private HashSet<LCS> GetSingleUnitLCSs(IEnumerable<SequencePath> listPaths, out int[] index) {
            HashSet<LCS> noLCSs = new HashSet<LCS>(LCS.InstanceForHash);
            HashSet<LCS> rst = new HashSet<LCS>(LCS.InstanceForHash);
            // 查找第一步骤的 LCV，所有长度为2中间可以连续或间隔
            foreach (SequencePath item in listPaths) {
                var first = item.First; // 长度为二的 LCS 的首个
                while( checkNextNull( first=first.Next, 3 ) ){
                //while ((first = first.Next).Next.Next != item.Last) {
                    int position = 2;
                    LCSUnit unit = new LCSUnit(first.Value[0], 1);
                    //todo : 设置最长跨度
                    for (var other = first.Next; other != item.Last; ++position, other = other.Next) {
                        //
                        if (position > MaxSpan) break;
                        if (position < MinSpan) continue;
                        //
                        LCS lcs = new LCS(0, unit, new LCSUnit(other.Value[0], position));
                        if (rst.Contains(lcs) || noLCSs.Contains(lcs)) { continue; }
                        IEnumerable<LinkedListNode<string>> links = this[first.Value];
                        for (int step = 0; step < position - 2; step++) {
                            links = links.MoveAllNext();
                        }
                        lcs.Support = links.Where(o => o.Value == other.Value).Count();
                        if (lcs.Support >= Threshold)
                            rst.Add(lcs);
                        else
                            noLCSs.Add(lcs);
                    }
                }
            }
            noLCSs = null;
            rst = new HashSet<LCS>(rst.OrderBy(o => o));
            index = new int[0];
            return rst;
        }
        bool checkNextNull(LinkedListNode<string> node, int steps) {
            if (node == null) return false;
            for (int i = 0; i < steps; i++) {
                node = node.Next;
                if (node == null) return false;                
            }
            return true;
        }
    }
}
*/